﻿namespace Digitalmes.Core.Domain.Repositories;

/// <summary>
/// 针对于 <see cref="ISugarQueryable{}"/> 对象扩展。
/// </summary>
public static class ISugarQueryableExtensions
{
    /// <summary>
    /// 分页查询。
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="query"></param>
    /// <param name="pageNumber">页号</param>
    /// <param name="pageSize">每页数量</param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public static async Task<(List<T> items, int total)> ToPagationAsync<T>(this ISugarQueryable<T> query,
        int pageNumber, int pageSize, CancellationToken cancellationToken = default)
        where T : class, new()
    {
        RefAsync<int> totalNumber = 0;
        var items = await query.ToPageListAsync(pageNumber, pageSize, totalNumber, cancellationToken);
        return (items, totalNumber);
    }

    /// <summary>
    /// 根据主键 Id 查找，主键实体为 <see cref="IEntityBase.Id"/>，没有找到则返回 null。
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="query"></param>
    /// <param name="id">Id</param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public static async Task<T?> GetByIdAsync<T>(this ISugarQueryable<T> query, long id, CancellationToken cancellationToken = default)
        where T : class, IEntityBase, new()
    {
        return await query.FirstOrDefaultAsync(s  => s.Id == id, cancellationToken);
    }

    /// <summary>
    /// 根据筛选条件查询第一条满足的数据，没有找到则返回 null。
    /// </summary>
    /// <returns></returns>
    public static async Task<T?> FirstOrDefaultAsync<T>(this ISugarQueryable<T> query, CancellationToken cancellationToken = default)
       where T : class, new()
    {
        return await query.FirstAsync(cancellationToken);
    }

    /// <summary>
    /// 根据筛选条件查询第一条满足的数据，没有找到则返回 null。
    /// </summary>
    /// <param name="where">筛选条件</param>
    /// <returns></returns>
    public static async Task<T?> FirstOrDefaultAsync<T>(this ISugarQueryable<T> query, Expression<Func<T, bool>> where,
       CancellationToken cancellationToken = default)
       where T : class, new()
    {
        return await query
            .Where(where)
            .FirstAsync(cancellationToken);
    }

    /// <summary>
    /// 根据筛选条件查询第一条满足的数据，没有找到则返回 null。
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="query"></param>
    /// <param name="where">筛选条件</param>
    /// <param name="order">排序</param>
    /// <param name="isDesc">是否按逆序查询</param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public static async Task<T?> FirstOrDefaultAsync<T>(this ISugarQueryable<T> query, Expression<Func<T, bool>> where,
        Expression<Func<T, object>> order, bool isDesc = true, CancellationToken cancellationToken = default)
        where T : class, new()
    {
        return await query
            .Where(where)
            .OrderBy(order, isDesc ? OrderByType.Desc : OrderByType.Asc)
            .FirstAsync(cancellationToken);
    }

    /// <summary>
    /// 根据筛选条件，按 <see cref="IEntityBase.Id"/> 排序获取最新的一条数据，没有找到则返回 null。
    /// </summary>
    /// <param name="where">筛选条件</param>
    /// <returns></returns>
    public static async Task<T?> LastOrDefaultAsync<T>(this ISugarQueryable<T> query, CancellationToken cancellationToken = default)
        where T : class, IEntityBase, new()
    {
        return await query
            .OrderBy(m => new { m.Id }, OrderByType.Desc)
            .FirstAsync(cancellationToken);
    }

    /// <summary>
    /// 根据筛选条件，按 <see cref="IEntityBase.Id"/> 排序获取最新的一条数据，没有找到则返回 null。
    /// </summary>
    /// <param name="where">筛选条件</param>
    /// <returns></returns>
    public static async Task<T?> LastOrDefaultAsync<T>(this ISugarQueryable<T> query, Expression<Func<T, bool>> where,
        CancellationToken cancellationToken = default)
        where T : class, IEntityBase, new()
    {
        return await query
            .Where(where)
            .OrderBy(m => new { m.Id }, OrderByType.Desc)
            .FirstAsync(cancellationToken);
    }

    /// <summary>
    /// 根据筛选条件，查找唯一的一条记录，没有找到则返回 null。
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="query"></param>
    /// <returns></returns>
    public static async Task<T?> SingleOrDefaultAsync<T>(this ISugarQueryable<T> query)
        where T : class, new()
    {
        return await query.SingleAsync();
    }

    /// <summary>
    /// 根据筛选条件，查找唯一的一条记录，没有找到则返回 null。
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="query"></param>
    /// <param name="where">筛选条件</param>
    /// <returns></returns>
    public static async Task<T?> SingleOrDefaultAsync<T>(this ISugarQueryable<T> query, Expression<Func<T, bool>> where)
        where T : class, new()
    {
        return await query
            .Where(where)
            .SingleAsync();
    }
}
